﻿// -----------------------------------------------------------------------------
// <copyright file="Settings.cs" company="Justin Wallace Saunders">
//     Copyright (c) Microsoft Public License. All rights reserved.
// </copyright>
// <author name="Justin Wallace Saunders" email="justinsa@live.ca" />
// -----------------------------------------------------------------------------
namespace Community.Tools.Database.Builder
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Reflection;

    /// <summary>
    /// This class is a singleton for assembly configuration settings.
    /// </summary>
    internal class Settings
    {
        /// <summary>
        /// Default execution timeout.
        /// </summary>
        private const int DefaultExecutionTimeout = 3000;

        /// <summary>
        /// The singleton instance of the Settings class.
        /// </summary>
        private static Settings instance = new Settings();

        /// <summary>
        /// Prevents a default instance of the Settings class from being created.
        /// </summary>
        private Settings()
        {
            this.Configuration = ConfigurationManager.OpenExeConfiguration(Assembly.GetAssembly(typeof(Settings)).Location);
            Substitutions = new Dictionary<string, string>();
        }

        /// <summary>
        /// Gets the usage message.
        /// </summary>
        public static string Usage
        {
            get
            {
                return @"Usage: Community.Tools.Database.Builder.exe ScriptRoot:<value> TargetLogRoot:<value> TargetDatabaseRoot:<value> TargetDatabaseServer:<value> TargetDatabaseName:<value> [<key>:<value>]*";
            }
        }

        /// <summary>
        /// Gets the configured value for the execution timeout.
        /// </summary>
        public static int ExecutionTimeout
        {
            get
            {
                int timeout = int.Parse(GetAppSetting(@"ExecutionTimeout"));
                return timeout > 0 ? timeout : DefaultExecutionTimeout;
            }
        }

        /// <summary>
        /// Gets the configured value for the database executable.
        /// </summary>
        public static string DatabaseExecutable
        {
            get
            {
                return GetAppSetting(@"DatabaseExecutable");
            }
        }

        /// <summary>
        /// Gets the configured value for the database executable arguments.
        /// Replace %TargetDatabaseServer% with Database Server.
        /// </summary>
        public static string DatabaseExecutableArguments
        {
            get
            {
                return GetAppSetting(@"DatabaseExecutableArguments").Replace("%TargetDatabaseServer%", DatabaseServer);
            }
        }

        /// <summary>
        /// Gets the configured value for the database directory.
        /// Replace %TargetDatabaseRoot% with Database Root.
        /// </summary>
        public static string DatabaseDirectory
        {
            get
            {
                return GetAppSetting(@"DatabaseDirectory").Replace("%TargetDatabaseRoot%", DatabaseRoot);
            }
        }

        /// <summary>
        /// Gets the configured value for the log directory.
        /// Replace %TargetLogRoot% with Log Root.
        /// </summary>
        public static string LogDirectory
        {
            get
            {
                return GetAppSetting(@"LogDirectory").Replace("%TargetLogRoot%", LogRoot);
            }
        }

        /// <summary>
        /// Gets the configured value for the error log file path.
        /// Replace %TargetLogRoot% with Log Root.
        /// </summary>
        public static string ErrorLogFilePath
        {
            get
            {
                return GetAppSetting(@"ErrorLogFilePath").Replace("%TargetLogRoot%", LogRoot);
            }
        }

        /// <summary>
        /// Gets the configured value for the log file path.
        /// Replace %TargetLogRoot% with Log Root.
        /// </summary>
        public static string LogFilePath
        {
            get
            {
                return GetAppSetting(@"LogFilePath").Replace("%TargetLogRoot%", LogRoot);
            }
        }

        /// <summary>
        /// Gets the configured value for the file tails.
        /// </summary>
        public static IEnumerable<string> FileTails
        {
            get
            {
                return GetAppSetting(@"FileTails").Split(new [] { '|' }, StringSplitOptions.RemoveEmptyEntries); 
            }
        }

        /// <summary>
        /// Gets the configured value for the SQL Scripts.
        /// Replace %ScriptRoot% with the local or absolute Script Root.
        /// </summary>
        public static IEnumerable<string> SqlScripts
        {
            get
            {
                string scripts = GetAppSetting(@"SqlScripts").Replace("%ScriptRoot%", ScriptRoot);
                IList<string> array = new List<string>(scripts.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries));
                for (int i = 0; i < array.Count; i++)
                {
                    array[i] = array[i].Trim();
                    if (string.IsNullOrWhiteSpace(array[i]))
                    {
                        array.RemoveAt(i);
                        --i;
                    }
                }

                return array;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether logging is enabled.
        /// </summary>
        public static bool LoggingEnabled { get; set; }

        /// <summary>
        /// Gets or sets the configured value for the database name.
        /// </summary>
        public static string DatabaseName { get; set; }

        /// <summary>
        /// Gets or sets the configured value for the database server.
        /// </summary>
        public static string DatabaseServer { get; set; }

        /// <summary>
        /// Gets or sets the substitution value of the %TargetDatabaseRoot% marker.
        /// </summary>
        public static string DatabaseRoot { get; set; }

        /// <summary>
        /// Gets or sets the substitution value of the %TargetLogRoot% marker.
        /// </summary>
        public static string LogRoot { get; set; }

        /// <summary>
        /// Gets or sets the substitution value of the %ScriptRoot% marker.
        /// </summary>
        public static string ScriptRoot { get; set; }

        /// <summary>
        /// Gets the set of substitution key-value pairs.
        /// </summary>
        public static IDictionary<string, string> Substitutions { get; private set; }

        /// <summary>
        /// Gets or sets the configuration information.
        /// </summary>
        private Configuration Configuration { get; set; }

        /// <summary>
        /// Gets the value of a key from the App Setting section of the
        /// assembly configuration file.
        /// </summary>
        /// <param name="key">The key to look-up</param>
        /// <returns>The value related to the key</returns>
        public static string GetAppSetting(string key)
        {
            return instance.Configuration.AppSettings.Settings[key].Value;
        }
    }
}